package com.dfe.backend.common.websocket.server;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 【描述】：
 *
 * @author LiChang
 * @since 2025-8-8 16:29
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{tokenId}")
public class WebSocketServer {

    /**
     * 使用map对象存放WebSocketServer对象，便于根据userId来获取对应的WebSocket，或者放redis里面
     */
    private static Map<String, WebSocketServer> webSocketServers = new ConcurrentHashMap<>();

    // 当前客户端的会话对象
    private Session session;

    /**
     * 对应的识别ID
     */
    private String tokenId = "";

    /**
     * 连接建立时触发
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("tokenId") String tokenId) {
        this.session = session;
        this.tokenId = tokenId;
        webSocketServers.put(tokenId, this);
        log.info("新连接【" + tokenId + "】加入！当前在线人数: " + webSocketServers.size());
        try {
            sendMessage("连接已建立！");
        } catch (Exception e) {
            log.error("websocket新建连接异常：", e);
        }
    }

    /**
     * 接收客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("来自客户端{}的消息:{}", this.tokenId, message);
        // 广播消息给所有客户端
        batchSendInfo(message);
//        for (WebSocketServer client : sessions) {
//            try {
//                client.sendMessage("服务器收到: " + message);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
    }

    /**
     * 连接关闭时触发
     */
    @OnClose
    public void onClose() {
        // 删除
        webSocketServers.remove(this.tokenId);
        System.out.println("连接关闭！当前在线人数: " + getUserCount());
    }

    /**
     * 发生错误时触发
     */
    @OnError
    public void onError(Throwable error) {
        log.info("websocket 发生错误,移除当前websocket:{},err:{}", this.tokenId, error.getMessage());
        webSocketServers.remove(this.tokenId);
    }

    /**
     * 发送消息 (同步发送)
     *
     * @param message 消息主题
     */
    private void sendMessage(String message) {
        synchronized (this) {
            try {
                this.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送消息 (同步发送)
     *
     * @param data 要发送的字节数组
     */
    private void sendMessage(byte[] data) {
        synchronized (this) {
            try {
                this.session.getBasicRemote().sendBinary(ByteBuffer.wrap(data));
            } catch (IOException e) {
                log.error("发送消息失败: {}", e.getMessage());
            }
        }
    }

    /**
     * 发送消息 (异步发送)
     *
     * @param message 消息主题
     */
    private void sendAsyncMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }

    /**
     * 向指定用户发送信息
     *
     * @param tokenId 用户id
     * @param wsInfo  信息
     */
    public static void sendInfo(String tokenId, String wsInfo) {
        if (webSocketServers.containsKey(tokenId)) {
            webSocketServers.get(tokenId).sendMessage(wsInfo);
        }
    }

    /**
     * 向指定用户发送Excel数据
     *
     * @param tokenId   用户ID
     * @param excelData Excel数据的字节数组
     */
    public static void sendExcelData(String tokenId, byte[] excelData) {
        if (webSocketServers.containsKey(tokenId)) {
            try {
                webSocketServers.get(tokenId).session.getBasicRemote().sendBinary(ByteBuffer.wrap(excelData));
                log.info("向用户 {} 发送Excel数据成功", tokenId);
            } catch (IOException e) {
                log.error("向用户 {} 发送Excel数据失败: {}", tokenId, e.getMessage());
            }
        } else {
            log.warn("用户 {} 不在线，无法发送Excel数据", tokenId);
        }
    }

    /**
     * 群发消息
     *
     * @param wsInfo
     * @param ids
     */
    public static void batchSendInfo(String wsInfo, List<String> ids) {
        ids.forEach(userId -> sendInfo(userId, wsInfo));
    }

    /**
     * 群发所有人
     *
     * @param wsInfo
     */
    public static void batchSendInfo(String wsInfo) {
        webSocketServers.forEach((k, v) -> v.sendMessage(wsInfo));
    }

    public static void batchSendBytes(byte[] bytes){
        webSocketServers.forEach((k, v) -> v.sendMessage(bytes));
    }

    /**
     * 获取当前连接信息
     *
     * @return
     */
    public static List<String> getIds() {
        return new ArrayList<>(webSocketServers.keySet());
    }


    /**
     * 获取当前连接数量
     *
     * @return int
     */
    public static int getUserCount() {
        return webSocketServers.size();
    }

}
